﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using BotonJXC.BLL;
using BotonJXC.Entity;
using BotonJXC.Util;
using ComponentFactory.Krypton.Toolkit;
using NHibernate;
using BotonJXC.DAO;

namespace BotonJXC.Forms.Controls
{
    public partial class UserAuthControl : BaseInfoControl
    {
        AuthResBLL _authResBll = new AuthResBLL();
        StoreBLL _storeBll = new StoreBLL();
        RoleDataAuthBLL _roleDataAuthBll = new RoleDataAuthBLL();
        RoleAuthResBLL _roleAuthResBll = new RoleAuthResBLL();
        IDictionary<int, object[]> _roleAuthDict = new Dictionary<int, object[]>();
        int _currRoleId = 0;
        bool _currAuthResUpdate = false;
        bool _currDataAuthUpdate = false;
        bool checkChild = true;
        public UserAuthControl()
        {
            InitializeComponent();
        }

        private void UserAuthControl_Load(object sender, EventArgs e)
        {
            if (!DesignMode)
            {
                TreeDataNode<AuthRes> authTree = _authResBll.FindAllToTree();
                foreach (TreeDataNode<AuthRes> d in authTree)
                {
                    TreeNode n = new TreeNode();
                    n.Text = d.Data.AuthResName;
                    n.Tag = d.Data;
                    kryptonTreeView1.Nodes.Add(n);
                    LoadAuthSubData(n, d);
                }

                IList<Store> _stores = _storeBll.FindAll();
                foreach (Store s in _stores)
                {
                    TreeNode n = new TreeNode();
                    n.Text = s.StoreName;
                    n.Tag = s;
                    kryptonTreeView2.Nodes.Add(n);
                    LoadDepDataAuthData(s, n);
                }

                roleControl1_SelectedRow(null, null);
            }
        }

        private void LoadDepDataAuthData(Store s, TreeNode n)
        {
            foreach (Department d in s.Departments)
            {
                TreeNode tn = new TreeNode();
                tn.Text = d.DepName;
                tn.Tag = d;
                n.Nodes.Add(tn);
            }
        }

        private void LoadAuthSubData(TreeNode treeNode, TreeDataNode<AuthRes> dataNode)
        {
            foreach (TreeDataNode<AuthRes> d in dataNode)
            {
                TreeNode n = new TreeNode();
                n.Text = d.Data.AuthResName;
                n.Tag = d.Data;
                treeNode.Nodes.Add(n);
                LoadAuthSubData(n, d);
            }
        }

        /// <summary>
        /// 根据父节点状态设置子节点的状态
        /// </summary>
        /// <param name="parentNode"></param>
        private void SetChildChecked(TreeNode parentNode)
        {
            foreach (TreeNode node in parentNode.Nodes)
            {
                node.Checked = parentNode.Checked;
                SetChildChecked(node);
            }
        }

        /// <summary>
        /// 根据子节点状态设置父节点的状态
        /// </summary>
        /// <param name="childNode"></param>
        private void SetParentChecked(TreeNode childNode, bool isResTree)
        {
            if (childNode.Parent != null)
            {
                bool isChecked = !isResTree;
                foreach (TreeNode n in childNode.Parent.Nodes)
                {
                    if (isResTree && n.Checked)
                    {
                        isChecked = true;
                        break;
                    }
                    else if (!isResTree && !n.Checked)
                    {
                        isChecked = false;
                        break;
                    }
                }
                childNode.Parent.Checked = isChecked;
                SetParentChecked(childNode.Parent, isResTree);
            }
            else
            {
                checkChild = true;
            }
        }

        private void roleControl1_PageChanged(object sender, EventArgs e)
        {

        }

        private void roleControl1_SelectedRow(object sender, EventArgs e)
        {
            if (roleControl1.SelectedItems != null && roleControl1.SelectedItems.Count > 0)
            {
                //保存前一个角色的权限
                SaveInfo();
                LoadRoleAuth(roleControl1.SelectedItems[0] as Role);
                _currRoleId = (roleControl1.SelectedItems[0] as Role).RoleId;
                _currAuthResUpdate = false;
                _currDataAuthUpdate = false;
            }
        }

        private void LoadRoleAuth(Role role)
        {
            if (role != null)
            {
                ClearTreeChecked(kryptonTreeView1);
                ClearTreeChecked(kryptonTreeView2);
                object[] roleAuths = null;
                if (!_roleAuthDict.TryGetValue(role.RoleId, out roleAuths))
                {
                    TreeDataNode<AuthRes> authRes = _authResBll.FindByRoleIdToTree(role.RoleId);
                    IList<RoleDataAuth> auths = _roleDataAuthBll.FindByRoleId(role.RoleId);
                    roleAuths = new object[2];
                    _roleAuthDict.Add(role.RoleId, roleAuths);
                    roleAuths[0] = authRes;
                    roleAuths[1] = auths;
                }
                checkChild = false;
                FillAuthResTree((TreeDataNode<AuthRes>)roleAuths[0]);

                FillDataAuthResTree((IList<RoleDataAuth>)roleAuths[1]);
                checkChild = true;
            }
        }

        private void FillDataAuthResTree(IList<RoleDataAuth> auths)
        {
            foreach (RoleDataAuth rda in auths)
            {
                TreeNode node = FindDataAuthNode(rda);
                if (node != null)
                {
                    node.Checked = true;
                    if (node.Level == 0)
                    {
                        foreach (TreeNode n in node.Nodes)
                        {
                            n.Checked = true;
                        }
                    }
                }
            }
        }
        TreeNode FindDataAuthNode(RoleDataAuth rda)
        {
            foreach (TreeNode n1 in kryptonTreeView2.Nodes)
            {
                if (rda.DepId == 0 && (n1.Tag as Store).StoreId == rda.StoreId)
                {
                    return n1;
                }
                else if (rda.DepId > 0)
                {
                    foreach (TreeNode n2 in n1.Nodes)
                    {
                        Department dp = n2.Tag as Department;
                        if (dp.DepId == rda.DepId)
                            return n2;
                    }
                }    
            }
            return null;
        }
        void ClearTreeChecked(KryptonTreeView treeView)
        {
            foreach (TreeNode tn in treeView.Nodes)
            {
                tn.Checked = false;
                SetChildChecked(tn);
            }
        }
        void FillAuthResTree(TreeDataNode<AuthRes> authRes)
        {
            foreach (TreeDataNode<AuthRes> n in authRes)
            {
                TreeNode node = FindAuthResNode(n.Data, kryptonTreeView1);
                if (node != null)
                {
                    node.Checked = true;
                }
                FillAuthResTree(n);
            }
        }

        TreeNode FindAuthResNode(AuthRes authRes, KryptonTreeView treeView)
        {
            foreach (TreeNode tn in treeView.Nodes)
            {
                AuthRes ar = tn.Tag as AuthRes;
                if (authRes.AuthResId == ar.AuthResId)
                    return tn;
                else
                {
                    TreeNode node = FindAuthResNode(authRes, tn);
                    if (node != null)
                        return node;
                }
            }
            return null;
        }

        TreeNode FindAuthResNode(AuthRes authRes, TreeNode node)
        {
            foreach (TreeNode tn in node.Nodes)
            {
                AuthRes ar = tn.Tag as AuthRes;
                if (authRes.AuthResId == ar.AuthResId)
                    return tn;
                else
                {
                    TreeNode n = FindAuthResNode(authRes, tn);
                    if (n != null)
                        return n;
                }
            }
            return null;
        }


        public override void SaveInfo()
        {
            if (_currRoleId > 0)
                SaveRoleAuth();
        }

        void SaveRoleAuth()
        {
            if (_currAuthResUpdate || _currDataAuthUpdate)
            {
                _roleAuthDict.Remove(_currRoleId);
                IList<RoleAuthRes> authRes = GetRoleAuthRes();
                IList<RoleDataAuth> dataAuths = GetRoleDataAuth();

                ITransaction trans = HBHelper.BeginTransaction();
                try
                {
                    if (_currAuthResUpdate)
                        _roleAuthResBll.Save(_currRoleId, authRes);
                    if (_currDataAuthUpdate)
                        _roleDataAuthBll.Save(_currRoleId, dataAuths);
                    trans.Commit();
                }
                catch (HibernateException ex)
                {
                    trans.Rollback();
                }
                finally
                {
                    HBHelper.Close();
                }
            }
        }

        /// <summary>
        /// 获取当前角色的数据权限
        /// </summary>
        /// <returns></returns>
        private IList<RoleDataAuth> GetRoleDataAuth()
        {
            IList<RoleDataAuth> dataAuths = new List<RoleDataAuth>();
            foreach (TreeNode node in kryptonTreeView2.Nodes)
            {
                if (node.Checked)
                {
                    RoleDataAuth rda = new RoleDataAuth();
                    Store s = node.Tag as Store;
                    rda.DepId = 0;
                    rda.RoleId = _currRoleId;
                    rda.StoreId = s.StoreId;
                    dataAuths.Add(rda);
                }
                else
                {
                    foreach (TreeNode n2 in node.Nodes)
                    {
                        if (n2.Checked)
                        {
                            RoleDataAuth rda = new RoleDataAuth();
                            Department d = n2.Tag as Department;
                            rda.DepId = d.DepId;
                            rda.RoleId = _currRoleId;
                            rda.StoreId = d.Store.StoreId;
                            dataAuths.Add(rda);
                        }
                    }
                }
            }
            return dataAuths;
        }
        /// <summary>
        /// 获取当前角色的功能权限
        /// </summary>
        /// <returns></returns>
        private IList<RoleAuthRes> GetRoleAuthRes()
        {
            IList<RoleAuthRes> authRes = new List<RoleAuthRes>();
            foreach (TreeNode node in kryptonTreeView1.Nodes)
            {
                if (node.Checked)
                {
                    authRes.Add(CreateRoleAuthRes(node.Tag as AuthRes));
                    FillRoleAuthRes(node, authRes);
                }
            }
            return authRes;
        }

        private void FillRoleAuthRes(TreeNode node, IList<RoleAuthRes> authRes)
        {
            foreach (TreeNode n in node.Nodes)
            {
                if (n.Checked)
                {
                    authRes.Add(CreateRoleAuthRes(n.Tag as AuthRes));
                    FillRoleAuthRes(n, authRes);
                }
            }
        }

        private RoleAuthRes CreateRoleAuthRes(AuthRes authRes)
        {
            RoleAuthRes rar = new RoleAuthRes();
            rar.AuthRes = authRes;
            rar.Role = new Role(_currRoleId);
            return rar;
        }

        private void kryptonTreeView1_AfterCheck(object sender, TreeViewEventArgs e)
        {
            if (checkChild)
            {
                checkChild = false;
                SetChildChecked(e.Node);
                SetParentChecked(e.Node, sender == kryptonTreeView1);
                if (sender == kryptonTreeView1)
                    _currAuthResUpdate = true;
                else
                    _currDataAuthUpdate = true;
            }
        }
    }
}
